package edu.scsu.csci.validator;

import java.lang.annotation.Annotation;
import java.util.HashMap;
import java.util.Map;

import edu.scsu.csci.IValidator;
import edu.scsu.csci.annotation.validator.ACharValidator;
import edu.scsu.csci.annotation.validator.ADateValidator;
import edu.scsu.csci.annotation.validator.ADoubleValidator;
import edu.scsu.csci.annotation.validator.AIntegerValidator;
import edu.scsu.csci.annotation.validator.ANullValidator;
import edu.scsu.csci.annotation.validator.AShortValidator;
import edu.scsu.csci.annotation.validator.AStringValidator;
import edu.scsu.csci.core.IRegistry;


/**
 * A registory for all the defined validators.
 * 
 * @author Maqbool Khan
 * @since jdk 1.5
 * @see
 */
public class ValidatorAnnotationRegistory implements IRegistry<Class<? extends Annotation>, IValidator> {
		
	/**
	 * mapping information for annotations and validators.
	 */
	private Map<Class<? extends Annotation>, IValidator> annotationMapping;
	
	/**
	 * singleton.
	 */
	private static ValidatorAnnotationRegistory instance;
	
	/**
	 * Returns the singleton registory instance.
	 * 
	 * @return
	 */
	public synchronized static ValidatorAnnotationRegistory getInstance(){
		if(instance == null){
			instance = new  ValidatorAnnotationRegistory();
			instance.setUp();
		}
		return instance;
	}
	
	/**
	 * Creates the validator registory.
	 */
	private ValidatorAnnotationRegistory(){
		this.annotationMapping = new HashMap<Class<? extends Annotation>, IValidator> ();
	}
		
	/**
	 * Registers the <code>validator</code> to be used for object of type class 
	 * <code>type</code> validation. The validation criteria is defined by the
	 * <code>annotation</code>.
	 * 
	 * @param type			the type of the object which needs to be validated.
	 * @param validator		the validator object.
	 * @param annotation	the validator annotaion defining the validation rules.
	 */
	public void register(Class<? extends Annotation> annotationType, IValidator validator){
		if(annotationType == null || validator == null){
			throw new IllegalArgumentException("Neither of the parameters can be null. validator: " + validator 
						+ "\t annotationType: " + annotationType);
		}
		this.annotationMapping.put(annotationType, validator);
	}
	
	/**
	 * @param type
	 * @return
	 */
	public IValidator get(Class<? extends Annotation> annotaionType){
		if(annotaionType == null){
			throw new IllegalArgumentException("annotaionType: " + annotaionType + " cannot be null.");
		}
		IValidator validator = annotationMapping.get(annotaionType);
		if(validator == null){
			return new NullValidator();
		}
		return validator;
	}
	
	/**
	 * Registers all the basic convertors.
	 */
	public void setUp(){
		this.register(AStringValidator.class, new StringValidator());
		this.register(AIntegerValidator.class, new IntegerValidator());
		this.register(ADoubleValidator.class, new DoubleValidator());
		this.register(ADateValidator.class, new DateValidator());
		this.register(ANullValidator.class, new NullValidator());
		this.register(AShortValidator.class, new ShortValidator());
		this.register(ADoubleValidator.class, new DoubleValidator());
		this.register(ACharValidator.class, new CharValidator());
	}
}
